`include "defines.v"
module bht(
  input clk,
  input rst_n,
  input [`ADDR_W-1:0] gen_bht_pc_i,
  output taken_o,

  input ex_bht_valid_i,
  input ex_bht_brunch_i,
  input [`ADDR_W-1:0]ex_bht_pc_i
);
  reg [9:0] bhr;
  wire [9:0] pht_rd_addr;  
  wire [9:0] pht_wr_addr;
  wire pht_wen;
  wire [1:0]pht_din,pht_dout1,pht_dout2;

  pht pht_inst(
    .clk  (clk),
    .rst_n(rst_n),
    .wr_addr (pht_wr_addr),
    .rd_addr (pht_rd_addr),
    .wen  (pht_wen),
    .din  (pht_din),
    .dout1 (pht_dout1) ,
    .dout2 (pht_dout2) 
  );
  /* 查询路径 */
  // 查询地址生成
  assign pht_rd_addr =  bhr ^ gen_bht_pc_i[9:0];
  // taken 判断
  assign taken_o = (pht_dout1 == 2'b11) || (pht_dout1 == 2'b10);
  /*-----------*/

  /* 更新路径 */
  //  BHR 的更新
  always@(posedge clk or negedge rst_n)
    if(~rst_n)
      bhr<= 'd0;
    else if(ex_bht_valid_i)
      bhr <= {bhr[8:0] , ex_bht_brunch_i};

  // PHT 更新
  assign pht_wen     = ex_bht_valid_i;
  assign pht_wr_addr = bhr ^ ex_bht_pc_i[9:0];
  assign pht_din     = ex_bht_brunch_i ? pht_dout2 + 1'b1 : pht_dout2 - 1'b1;
  /*-----------*/
endmodule 

module pht(
  input clk,
  input rst_n,
  input [9:0] rd_addr,
  input [9:0] wr_addr,
  input wen,
  input [1:0]din,
  output[1:0]dout1,
  output[1:0]dout2
);
  reg [1:0] pht [0:1023];

  genvar i;
  generate 
    for(i=0;i<1024;i=i+1)begin
      always@(posedge clk or negedge  rst_n)
      if(~rst_n)
        pht[i] <= 2'b00;
      else if(wen && wr_addr == i)
        pht[i] <= din;                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                  
    end
  endgenerate

  assign dout1 = pht[rd_addr];
  assign dout2 = pht[wr_addr];

endmodule